/*
 * main.cpp
 *
 *  Created on: 2013. 1. 31.
 *      Author: jjaehuny
 */

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <Dispatcher/Static.h>

#include "src/ListenHandler.h"
#include "src/ChannelServer.h"
#include "src/MemCached.h"

#include "idl/iFriends.h"

#include "src/User.h"

#include <vector>
#include <string>

#include "src/Static.h"


bool resource_database()
{
	Database::ResultSet res = Database::Execute(1, "SELECT * FROM env_database WHERE active = 1");
	if (0 != res.GetSQLError())
	{
		std::cerr << "resource_database query fail" << std::endl;
		return false;
	}

	if (res.end() == res.begin())
	{
		std::cerr << "resource_database query result is nothing" << std::endl;
		return false;
	}

	for(auto itr = res.begin(); itr != res.end(); itr++)
	{
		//int seq = itr->getInt("seq");
		int active = itr->getInt("active");
		int type = itr->getInt("type");
		std::string host = itr->getString("host");
		std::string user = itr->getString("user");
		std::string password = itr->getString("password");
		std::string database = itr->getString("database");
		std::string desc = itr->getString("desc");

		if (active <= 0)
			continue;

		if(false == Database::Connect(type, host.c_str(), 3306, user.c_str(), password.c_str(), database.c_str()))
		{
			std::cerr << "DB Connect Error" << std::endl;
			return false;
		}
	}

	return true;
}

bool resource_memcache()
{
	Database::ResultSet res = Database::Execute(1, "SELECT * FROM env_memcache WHERE active = 1");
	if (0 != res.GetSQLError())
	{
		std::cerr << "resource_memcache query fail" << std::endl;
		return false;
	}

	if (res.end() == res.begin())
	{
		std::cerr << "resource_memcache query result is nothing" << std::endl;
		return false;
	}

	int count = 0;
	std::stringstream value;

	for(auto itr = res.begin(); itr != res.end(); itr++)
	{
		if (0 < count) { value << ","; }

		value << itr->getString("ip");
		value << ":";
		value << itr->getString("port");

		count++;
	}

	LOG(INF, value.str().c_str());
	if( !Memcache->Init(value.str().c_str()) )
	{
		LOG(ERR, "memcached error");
		exit(0);
	}

//	Memcache->FlushAll();

	return true;
}

int main(int argc, char **argv) {

	std::mutex mutex_;
	std::condition_variable condition_;

	if(false == Logger::Init())
	{
		return 0;
	}

	Logger::SetLevelProperty(Logger::LOG_LEVEL_DEV, Logger::LOG_STDERR|Logger::LOG_FILE);
	Logger::SetLevelProperty(Logger::LOG_LEVEL_INF, Logger::LOG_STDERR|Logger::LOG_FILE);
	Logger::SetLevelProperty(Logger::LOG_LEVEL_ERR, Logger::LOG_STDERR|Logger::LOG_FILE|Logger::LOG_SYSLOG);

	boost::property_tree::ptree ptree_;
	try
	{
		boost::property_tree::xml_parser::read_xml("./conf/FriendsServer.xml", ptree_);
	}
	catch (boost::exception& e)
	{
		LOG(ERR, "fail to read config(./conf/FriendsServer.xml)");
		return 0;
	}

	LOG(INF, "========== FRIENDS SERVER Server Start ==========");
	LOG(INF, "boost ver : ", BOOST_LIB_VERSION);
	LOG(INF, "build ver : ", __DATE__, " ", __TIME__);

	if(false == Dispatcher::Init())
	{
		LOG(ERR, "fail to init Dispatcher lib");
		return 0;
	}

	int listenPort = ptree_.get<int>("server.session.<xmlattr>.port");
	std::shared_ptr< ::FriendsServer::ListenHandler> pListenHandler(new ::FriendsServer::ListenHandler());
	if(false == Dispatcher::Listen(listenPort, pListenHandler.get(), 1024))
	{
		LOG(ERR, "fail to listen(port:", listenPort, ")");
		return false;
	}


	if(false == Database::Init())
	{
		return 0;
	}

	const char * host =  ptree_.get<std::string>("server.database.connection.<xmlattr>.host").c_str();
	const char * id = ptree_.get<std::string>("server.database.connection.<xmlattr>.user").c_str();
	const char * pass = ptree_.get<std::string>("server.database.connection.<xmlattr>.passwd").c_str();
	const char * schema = ptree_.get<std::string>("server.database.connection.<xmlattr>.db").c_str();

	if(false == Database::Connect(1, host, 3306, id, pass, schema))
	{
		std::cerr << "DB Connect Error" << std::endl;
		return 0;
	}

	if (false == resource_database())
	{
		std::cerr << "resource_database Error" << std::endl;
		return 0;
	}

	if (false == resource_memcache())
	{
		std::cerr << "resource_memcache Error" << std::endl;
		return 0;
	}


	::FriendsServer::Static clsStatic;

	LOG(DEV, "is_test=", FriendsServer::Static::Instance().is_test);
	LOG(DEV, "rankCycle=", FriendsServer::Static::Instance().rankCycle);
	// test code
	FriendsServer::Static::Instance().is_test = ptree_.get<int>("test.<xmlattr>.is_test");
	FriendsServer::Static::Instance().rankCycle = ptree_.get<int>("test.<xmlattr>.rank_cycle");
	LOG(DEV, "is_test=", FriendsServer::Static::Instance().is_test);
	LOG(DEV, "rankCycle=", FriendsServer::Static::Instance().rankCycle);

	LOG(INF, "listen(port:", listenPort, ")");
	LOG(INF, "[FRIENDS SERVER START]");

	std::unique_lock<std::mutex> lock(mutex_);
	condition_.wait(lock);
	return 0;
}

